#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<ctype.h>
#include<sys/wait.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#define NUM 1024
#define OT_NUM 200
#define O_INPUT 1
#define O_OUTPUT 2
#define O_NONE 0
#define O_APPENDED 3
#define Tripspace(start) do{\
    while(isspace(*start)){start++;}\
  }while(0)
char getOrder[NUM];
char* OrderTake[OT_NUM];
int Filetype;
char* Filename;

void *CommendCheak(char* order)
{
  char* start = order;
  char* end = order + strlen(order);
  while(start<end)
  {
    if(*start == '>')
    {
      Filetype = O_OUTPUT;
      *start = '\0';
      start++;
      if(*start == '>')
      {
        Filetype = O_APPENDED;
        start++;
      }
      Tripspace(start);
      Filename = start;
      break;
    }
    else if(*start == '<')
    {
      Filetype = O_INPUT;
      *start = '\0';
      start++;
      Tripspace(start);
      Filename = start;
      break;
    }
    else 
    {
        start++;
    }
  }
}

int main()
{ 
  while(1)
  { 
    Filename = NULL;
    Filetype = O_NONE;
    printf("用户名@用户组# ");
    fflush(stdout);
    //get your command in terminal 
    //The result why "-1" is to save a place to the \0
    char* s = fgets(getOrder,sizeof(getOrder)-1,stdin);
  assert(s!=NULL);
  (void)s;
  //To delete the last \n we have input
  getOrder[strlen(getOrder)-1] = 0;
  //after gets the command,we need to get all the singal order from <getOrder>
  CommendCheak(getOrder);
  OrderTake[0] = strtok(getOrder," ");
  int i = 1;
  if(strcmp(OrderTake[0],"ls") == 0)
  {
    OrderTake[i++] = (char*)"--color=auto";
  }
  else if(strcmp(OrderTake[0],"ll") == 0)
  {
    OrderTake[0] = (char*)"ls";
    OrderTake[i++] = (char*)"--color=auto";
    OrderTake[i++] = (char*)"-al";
  }
  while(OrderTake[i++] = strtok(NULL," "));
#ifdef DEBUG
  for(int o = 0;OrderTake[o];o++)
  {
    printf("%s\n",OrderTake[o]);
  }
#endif
  if(strcmp(OrderTake[0],"cd") ==0)
  {
    if(OrderTake[1] != NULL)
    chdir(OrderTake[1]);
  }
  //after we take the order,we will use they to quote system's order.
  //we will use fork create a child thread to use the system order.
  pid_t id = fork();
  assert(id != -1);
  if(id == 0)
  {
    //means child thread create sucess
    switch(Filetype)
    {
      case O_NONE:
        break;
      case O_INPUT:
        {
          int fd = open(Filename,O_RDONLY,0666);
          if(fd < 0)
          {
            exit(3);
          
          }
          dup2(fd,0);
        }
        break;
      case O_OUTPUT:
      case O_APPENDED:
        {
          int flags = O_WRONLY | O_CREAT;
          if(Filetype == O_APPENDED) flags |= O_APPEND;
          int fd = open(Filename,flags,0666);
          if(fd<0)
          { 
            exit(3);
          }
          dup2(fd,1);
        }
        break;
    }
    execvp(OrderTake[0],OrderTake);
    exit(2);
  }
  int status = 0;
  pid_t ret = waitpid(id,&status,0);
#ifdef DEBUG
  printf("exitcode : %d\n",status&0x7F);
#endif
}
}

